//
//  MediaBookBase.m
//  Dolphin
//
//  Created by Matthew on 11-7-26.
//  Copyright 2011年 __MyCompanyName__. All rights reserved.
//

#import "MediaBookBase.h"

@implementation MediaBookBase
@synthesize gDataSet;
@synthesize curOrientationView;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // Initialization code
        curOrientationView = @"v";
    }
    return self;
}

-(void) updateBook:(int) updatePageId
{
    BOOL pageFounded = FALSE;
    
    NSMutableSet *rangeIdSet = [[NSMutableSet alloc] init];
    NSMutableDictionary *usedIdDict = [[NSMutableDictionary alloc] init];
    

    //init range id set
    for (int i= -active_page_range; i<=active_page_range; i++) 
    {
        if(i != 0 && updatePageId+i>=0 && updatePageId+i < page_num)
        {
            NSNumber *num = [NSNumber numberWithInt:updatePageId+i];
            [rangeIdSet addObject:num];
        }
    }
    
    //check if page need gen
    for (SinglePage* page in pages) 
    {
        if(page.page_id == updatePageId)
        {
            pageFounded = TRUE;
        }
        
        //delete the unused page
        if (abs(page.page_id-updatePageId)>active_page_range) 
        {
            if (!page.hasMedia) 
            {
                [recycleSet addObject:page];
            }
        }
        else //save the page id which in range
        {
            [usedIdDict setValue:@"1" forKey:[NSString stringWithFormat:@"%d",page.page_id]];
        }
    }
    
    if(!pageFounded)
    {
        NSNumber *tmp_num = [NSNumber numberWithInt:updatePageId];
        
        if ([self checkNodeInQueue:updatePageId] == FALSE)
        {
            [genNodeQueue insertObject:tmp_num atIndex:0];
        }
    }
    
    //add other pages in range
    for(NSNumber *num in rangeIdSet)
    {
        NSString *id = [usedIdDict objectForKey:[NSString stringWithFormat:@"%@",num]];
        int target_id = [num intValue];
        
        if(id &&[ id isEqualToString:@"1"]) // if page already exists
        {
            //do nothing
        }
        else
        {
            if ([self checkNodeInQueue:target_id] == FALSE)
            { 
                [genNodeQueue addObject:num];
            }
        }
    }
    
    [rangeIdSet removeAllObjects];
    [rangeIdSet release];
    
    [usedIdDict removeAllObjects];
    [usedIdDict release];
}

//object management proc:generate and recycle
-(void) objectManageProc
{
    //int pre_index = cur_index;
    if (false)//on_auto_play)
    {
        if (auto_play_tick_count<auto_play_tick_limit)
        {
            auto_play_tick_count++;
        }
        else
        {
            auto_play_tick_count = 0;
            int target_id = (cur_index+1)%page_num;
            [scrollView setContentOffset:CGPointMake(target_id*page_width, 0) animated:NO];
            
            SinglePage *tmpPage = [self getPageById:target_id];
            if (tmpPage != Nil) 
            {
                tmpPage.alpha = 0.0f;
            }
        }
    }
    
    if (gDataSet.landscape_two_page && [curOrientationView isEqualToString:@"h"]) 
    {
        cur_index = round(scrollView.contentOffset.x/(scrollView.frame.size.width/2));
    }
    else
    {
        cur_index = round(scrollView.contentOffset.x/(scrollView.frame.size.width));
    }
    
    if (discrete_count<1) 
    {
        discrete_count++;
    }
    else
    {
        discrete_count = 0;
        [self checkIfCurNodeNotExist];
        [self newPageGenAction];
        [self recycleAction];
        
        //MPMovieController display status bar
        if(status_bar_hidden)
        {
            [[UIApplication sharedApplication] setStatusBarHidden:YES];
        }
        
        [topBar updateIndex:cur_index+1 _totalIndex:page_num];
    }
    
    if (!(gDataSet.landscape_two_page && [curOrientationView isEqualToString:@"h"])) 
    {    
        [self closeMediaPage];
    }
    
    [self chkAndGenNewLayerAtCurIndex];
    
    [self updateSlideshowAutoPlay:cur_index];
    
    if (cur_index == 0) 
    {
        [topBar manuallyMusicOff];
    }
    else
    {
        [topBar manuallyMusicOn];
    }
}


-(void) newPageGenAction
{
    if([genNodeQueue count]>0 )
    {
        //if current index is in queue, gen it first:
        int the_priority_index = [self getPriorityIdIndex];
        
        if(the_priority_index== -1)//no priority node found.
        {
            the_priority_index = 0;
        }
        
        NSNumber *gen_id = [genNodeQueue objectAtIndex:the_priority_index];
        int gen_int = [gen_id intValue];
        
        [genNodeQueue removeObjectAtIndex:the_priority_index];
        
        //page has not yet been gen
        if ([self checkNodeGenerated:gen_int] == FALSE)
        {
            if (abs(gen_int-cur_index) <= active_page_range) 
            {
                [self createNewPage:gen_int];  
            }  
        }
    }
}

-(void) createNewPage:(int)newPageId
{
    if (newPageId<0 || newPageId >= [bookXMLParser.pagesArr count]) 
    {
        return;
    }
    
    NSMutableArray *everyPageLayerInfo = [bookXMLParser.pagesArr objectAtIndex: newPageId];
    
    int div_num = 1;
    if (gDataSet.landscape_two_page && [curOrientationView isEqualToString:@"h"])
    {
        div_num = 2;
    }
    
    SinglePage *singlePage = [[SinglePage alloc] initWithFrame:CGRectMake(newPageId*page_width/div_num, 0,page_width/div_num,page_height)];
    
    [singlePage initWithPageInfo:[bookXMLParser.pagePropArr objectAtIndex:newPageId]];          
    singlePage.page_id = newPageId;
    
    if (gDataSet.landscape_two_page && [curOrientationView isEqualToString:@"h"])
        [singlePage layoutAdjustWithOrientation:0 isLandScapeTwoPage:gDataSet.landscape_two_page isInit:TRUE];
    else
        [singlePage layoutAdjustWithOrientation:0 isLandScapeTwoPage:gDataSet.landscape_two_page isInit:FALSE];
    
    if (everyPageLayerInfo != Nil && [everyPageLayerInfo count]>0) 
    {
        singlePage.layers_num = [everyPageLayerInfo count];
        
        //only apply pre-init solution with image layer
        LayerInfo *everyLayer = [[LayerInfo alloc] init];
        [[everyPageLayerInfo objectAtIndex:0] copyWithNewInfoObject:everyLayer];
        
        if([everyLayer.type isEqualToString:@"img"])
        {
            [self addLayerAtPage:singlePage inLayerInfoArr:everyPageLayerInfo inLayerIndex:0];
        }
        
        [everyLayer release];
    }
    
    //check if has media
    for (int i = 0; i < [everyPageLayerInfo count] ; i++) 
    {
        LayerInfo *everyLayer = [everyPageLayerInfo objectAtIndex:i] ;
        
        if ([everyLayer.type isEqualToString: @"video"] || [everyLayer.type isEqualToString:@"audio"]) 
        {
            singlePage.hasMedia = TRUE;
            singlePage.mediaAutoPlay = everyLayer.autoPlay;
            singlePage.mediaIndex = i;
        }
    }
    
    [pages addObject:singlePage];
    [scrollView addSubview:singlePage];
}

-(void) addLayerAtPage:(SinglePage *) inPage 
        inLayerInfoArr:(NSMutableArray*) layerInfoArr
        inLayerIndex  :(int) layerIndex
{
    if (inPage == Nil || layerInfoArr == Nil)
    {
        return;
    }
    
    if (layerIndex<0 || layerIndex>= [layerInfoArr count]) 
    {
        return;
    }
    LayerInfo *everyLayer = [[LayerInfo alloc] init];
    [[layerInfoArr objectAtIndex:layerIndex] copyWithNewInfoObject:everyLayer];
    
    if([everyLayer.type isEqualToString:@"img"])
    {
        CGFloat imgW = everyLayer.width;
        CGFloat imgH = everyLayer.height;
        
        if(fit_with_screen && inPage.resizeMode == 0)
        {
            imgW = page_width;
            imgH = page_height;
        }
        else if(fit_with_screen && inPage.resizeMode == 1 && 
                (imgW == 0 || imgH == 0) && layerIndex == 0)
        {
            imgW = gDataSet.page_width;
            imgH = gDataSet.page_height;
        }
        
        [inPage addImage:everyLayer.resPath 
                  imgPos:CGPointMake(everyLayer.x, everyLayer.y)  
                 imgSize:CGSizeMake(imgW, imgH)
         useOriginalSize:everyLayer.useOriginalSize
               ratioMode:everyLayer.ratioMode
                targetId:everyLayer.target_page_id
               layerInfo:everyLayer];
    }
    else if([everyLayer.type isEqualToString:@"video"])
    {
        inPage.hasMedia = TRUE;
        
        if (fit_with_screen && inPage.resizeMode == 0) 
        {
            everyLayer.width = page_width;
            everyLayer.height = page_height;
        }
        else if(fit_with_screen && inPage.resizeMode == 1 && 
                (everyLayer.width == 0 || everyLayer.height == 0) && layerIndex == 0)
        {
            everyLayer.width = gDataSet.page_width;
            everyLayer.height = gDataSet.page_height;
        }
        
        [inPage addVideoPlayer:everyLayer.resPath
                      videoPos:CGPointMake(everyLayer.x, everyLayer.y) 
                     videoSize:CGSizeMake(everyLayer.width,everyLayer.height) 
                      autoPlay:everyLayer.autoPlay  
                        isLoop:everyLayer.isLoop
                     layerInfo:everyLayer
             slideshowAutoPlay:on_auto_play
                    slideBgmOn:[topBar musicOn]
                                 fade:everyLayer.fade];
    }
    else if([everyLayer.type isEqualToString:@"imgslider"])
    {
        [inPage addBtnSlide:everyLayer.imgArr slidePos:CGPointMake(everyLayer.x, everyLayer.y) 
                  slideSize:CGSizeMake(everyLayer.width, everyLayer.height) imgSize:CGSizeMake(everyLayer.imgWidth,everyLayer.imgHeight) layerInfo:everyLayer];
    }
    else if([everyLayer.type isEqualToString:@"audio"])
    {
        inPage.hasMedia = TRUE;
        [inPage addAudio:everyLayer.resPath 
                audioPos:CGPointMake(everyLayer.x,everyLayer.y) 
                autoPlay:everyLayer.autoPlay isLoop:everyLayer.isLoop isButtonShow:everyLayer.showButton layerInfo:everyLayer];
    }
    
    [everyLayer release]; 
}

-(BOOL) checkNodeInQueue:(int) inNodeId
{
    for (int i = 0; i<[genNodeQueue count]; i++) 
    {
        int tmp_id = [[genNodeQueue objectAtIndex:i] intValue];
        
        if(tmp_id == inNodeId)
        {
            return TRUE;
        }
    }
    
    return FALSE;
}

-(BOOL) checkNodeGenerated:(int) inNodeId
{
    for (SinglePage* page in pages) 
    {
        if(page.page_id == inNodeId)
        {
            return TRUE;
        }
    }
    
    return  FALSE;
}


-(SinglePage *) getPageById:(int) inNodeId
{
    for (SinglePage* page in pages) 
    {
        if(page.page_id == inNodeId)
        {
            return page;
        }
    }
    return Nil;
}

-(int) getPriorityIdIndex
{
    int plus_min_dis = 10000;
    int minus_min_dis = 10000;
    
    int plus_min_id = -1;
    int minus_min_id = -1;
    
    for (int i = 0; i<[genNodeQueue count]; i++)
    {
        NSNumber *gen_id = [genNodeQueue objectAtIndex:i];
        int gen_int = [gen_id intValue];
        
        if(gen_int == cur_index)
        {
            return i;
        }
        
        int dis = abs(gen_int-cur_index);
        if (dis<plus_min_dis || 
            dis<minus_min_dis) 
        {
            if (gen_int>cur_index) 
            {
                plus_min_dis = dis;
                plus_min_id = i;
            }
            else
            {
                minus_min_dis = dis;
                minus_min_id = i;
            }
        }
    }
    
    if (avg_distance>0 && plus_min_id>=0)
    {
        return plus_min_id;
    }
    else if(avg_distance<0 && minus_min_id>=0)
    {
        return minus_min_id;
    }
    else
    {
        return -1;
    }
}

-(void) checkIfCurNodeNotExist
{
    if ([self checkNodeGenerated:cur_index] == FALSE) 
    {
        if ([self checkNodeInQueue:cur_index] == FALSE)
        {
            [self updateBook:cur_index];
        }
    }
    else
    {
        SinglePage* tmpPage = [self getPageById:cur_index];
        
        if (tmpPage.alpha == 0) 
        {
            [UIView transitionWithView:tmpPage duration:0.1f 
                               options:UIViewAnimationCurveEaseIn 
                            animations:^(void) {tmpPage.alpha = 1.0f;} 
                            completion:NULL];
        }
    }
}

-(void) chkAndGenNewLayerAtCurIndex
{
    if(cur_index>=0 && cur_index<page_num)
    {
        for (SinglePage* page in pages) 
        {
            if(page.page_id == cur_index)
            {
                int index = [page curLayersNum] ;//the possible target id
                if (index < page.layers_num )//&& index>0) 
                {
                    NSMutableArray *everyPageLayerInfo = [bookXMLParser.pagesArr objectAtIndex: page.page_id];
                    [self addLayerAtPage:page inLayerInfoArr:everyPageLayerInfo inLayerIndex:index];
                }
                return;
            } 
        }
    }
}



//check slide show auto play
-(void) updateSlideshowAutoPlay: (int) inIndex
{
    SinglePage* tmpPage = [self getPageById:inIndex];
    
    if (tmpPage == Nil) 
    {
        return;
    }
    
    if(tmpPage.hasMedia == TRUE)
    {
        if([topBar musicOn])
        {
            slide_bgm_on_stack = TRUE;
            //[topBar manuallyMusicOff];
        }
        
        if([topBar slideOnAutoPlay])
        {
            if(tmpPage.mediaAutoPlay)
            {
                slide_play_on_stack = TRUE;
                [topBar manuallyPauseSlide];
            }
            else if(tmpPage.mediaIndex >= 0)
            {
                UIComponentBase *tmpMediaPlayer = [tmpPage getLayerAtIndex:tmpPage.mediaIndex];
                
                if (tmpMediaPlayer != Nil && [tmpMediaPlayer mediaOnPlaying]) 
                {
                    slide_play_on_stack = TRUE;
                    [topBar manuallyPauseSlide];
                }
            }
        }
    }
    else
    {
        if (slide_play_on_stack) 
        {
            [topBar manuallyPlaySlide];
            on_auto_play = TRUE;
            auto_play_tick_count = 0;
            slide_play_on_stack = FALSE;
        }
        
        if(slide_bgm_on_stack)
        {
            [topBar manuallyMusicOn];
            slide_bgm_on_stack = FALSE;
        }
    }
}

-(void) closeMediaPage
{
    //delete unuseful media layer
    for (SinglePage* page in pages) 
    {
        if(abs(page.page_id-cur_index) >= 1 && page.hasMedia)
        {
            [tempMediaSet addObject:page];
        }
    }
    
    for (SinglePage* tempSinglePage in tempMediaSet) 
    {
        if (tempSinglePage != Nil) 
        {
            [pages removeObject:tempSinglePage]; 
            [tempSinglePage reset];
            [tempSinglePage removeFromSuperview];
            [tempSinglePage release];
        }
    }
    
    [tempMediaSet removeAllObjects];
}

-(void) recycleAction
{
    SinglePage *targetDelPage;
    int len = 0;
    int max_len = 0;
    BOOL findTarget = FALSE;
    
    for (SinglePage *page in recycleSet ) 
    {   //remove the fartest page first
        len = abs(page.page_id-cur_index);
        
        if (findTarget == FALSE) 
        {
            targetDelPage = page;
            findTarget  = TRUE;
            max_len = len;
        }
        else
        {
            if(len>max_len)
            {
                max_len = len;
                targetDelPage = page;
            }
        } 
    }
    
    if(findTarget)
    {
        [recycleSet removeObject:targetDelPage];
        
        if(abs(targetDelPage.page_id-cur_index)>active_page_range)
        {
            [pages removeObject:targetDelPage]; 
            [targetDelPage reset];
            [targetDelPage removeFromSuperview];
            [targetDelPage release];
        }
    }
}

- (void)dealloc
{
    [super dealloc];
}

@end
